package com.gxar.quick.ar.server.db.service;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxar.common.entity.PageResult;
import com.gxar.common.entity.Result;
import com.gxar.common.entity.SlippageResult;
import com.gxar.common.entity.login.UserProfile;
import com.gxar.common.exception.APIRuntimeException;
import com.gxar.common.utils.PageUtils;
import com.gxar.common.utils.SnowFlakeUtils;
import com.gxar.fusion.redis.service.RedisService;
import com.gxar.quick.ar.server.base.common.constant.RedisConstant;
import com.gxar.quick.ar.server.base.common.constant.WorksConstant;
import com.gxar.quick.ar.server.base.common.enums.UserWorksSourceEnum;
import com.gxar.quick.ar.server.base.common.enums.UserWorksTypeEnum;
import com.gxar.quick.ar.server.base.common.properties.UserProperties;
import com.gxar.quick.ar.server.base.model.ResultCodeEnum;
import com.gxar.quick.ar.server.base.model.plaza.mapper.PlazaMapStruct;
import com.gxar.quick.ar.server.base.model.plaza.vo.request.AdminPublishPlazaRequest;
import com.gxar.quick.ar.server.base.model.plaza.vo.request.AdminUpdatePlazaRequest;
import com.gxar.quick.ar.server.base.model.plaza.vo.response.*;
import com.gxar.quick.ar.server.base.model.works.mapper.WorksMapStruct;
import com.gxar.quick.ar.server.base.model.works.vo.response.WorksInfoResponse;
import com.gxar.quick.ar.server.db.mapper.PlazaMapper;
import com.gxar.quick.ar.server.db.mapper.UserInfoMapper;
import com.gxar.quick.ar.server.db.mapper.UserWorksMapper;
import com.gxar.quick.ar.server.db.model.PlazaEntity;
import com.gxar.quick.ar.server.db.model.UserInfoEntity;
import com.gxar.quick.ar.server.db.model.UserWorksEntity;
import com.gxar.quick.ar.server.db.model.WorksEntity;
import com.gxar.quick.ar.server.db.repository.PlazaRepository;
import com.gxar.quick.ar.server.db.repository.WorksRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author linsy
 * @version 1.0
 * @created 2023/11/6 17:58
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PlazaService {

    private final UserProperties userProperties;

    private final RedisService redisService;
    private final PlazaMapper plazaMapper;
    private final UserInfoMapper userInfoMapper;
    private final PlazaRepository plazaRepository;
    private final UserWorksMapper userWorksMapper;
    private final WorksRepository worksRepository;

    /**
     * 广场列表查询
     *
     * @param userProfile       用户
     * @param nextId            下一页请求信息
     * @param userWorksTypeEnum 作品类型
     * @return 响应
     */
    public SlippageResult<PlazaListResponse> list(UserProfile userProfile, String nextId, UserWorksTypeEnum userWorksTypeEnum) {
        int pageNumber = 1;
        if (StringUtils.isNotBlank(nextId)) {
            String pageKey = String.format(RedisConstant.PLAZA_PAGE_KEY, userWorksTypeEnum.getName(), nextId);
            Object pageInfo = redisService.get(pageKey);
            if (pageInfo != null) {
                pageNumber = Integer.parseInt(pageInfo.toString());
                redisService.remove(pageKey);
            }
        }
        PageHelper.startPage(pageNumber, WorksConstant.DEFAULT_PLAZA_QUERY_LIMIT);
        List<PlazaListResponse> plazaListResponses = plazaMapper.queryPage(Objects.nonNull(userProfile) ? userProfile.getId() : null, userWorksTypeEnum.getCode());
        if (CollectionUtils.isEmpty(plazaListResponses)) {
            return SlippageResult.build(null, Collections.emptyList());
        }
        // 查询用户信息
        List<String> userIdList = plazaListResponses.stream().map(PlazaListResponse::getUserId).collect(Collectors.toList());
        List<UserInfoEntity> userInfoEntityList = userInfoMapper.queryByUserIdList(userIdList);
        Map<Long, UserInfoEntity> userInfoMap = Optional.ofNullable(userInfoEntityList).orElse(Collections.emptyList()).stream().collect(Collectors.toMap(UserInfoEntity::getUserId, t -> t, (t1, t2) -> t1));
        for (PlazaListResponse plazaListResponse : plazaListResponses) {
            UserInfoEntity userInfoEntity = userInfoMap.get(Long.parseLong(plazaListResponse.getUserId()));
            if (Objects.nonNull(userInfoEntity)) {
                plazaListResponse.setAvatar(StringUtils.isBlank(userInfoEntity.getAvatar()) ? userProperties.getDefaultAvatar() : userInfoEntity.getAvatar());
                plazaListResponse.setUserName(StringUtils.isBlank(userInfoEntity.getName()) ? userProperties.getDefaultName() : userInfoEntity.getName());
            }
        }
        String nextedId = SnowFlakeUtils.getInstance().nextId();
        String pageKey = String.format(RedisConstant.PLAZA_PAGE_KEY, userWorksTypeEnum.getName(), nextedId);
        redisService.set(pageKey, pageNumber + 1);
        redisService.expire(pageKey, RedisConstant.DEFAULT_EXPIRE_SECONDS);
        return SlippageResult.build(nextedId, plazaListResponses);
    }

    /**
     * 广场作品喜欢
     *
     * @param userProfile 用户信息
     * @param id          广场id
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public PlazaLikeResponse favorites(UserProfile userProfile, Long id) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (!plazaEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NOT_EXIST);
        }
        PlazaEntity plazaEntity = plazaEntityOptional.get();
        Long worksId = plazaEntity.getWorksId();
        UserWorksEntity userWorksEntity = userWorksMapper.queryByWorksAndSource(userProfile.getId(), worksId, UserWorksSourceEnum.PLAZA.getCode());
        if (Objects.isNull(userWorksEntity)) {
            // 收藏
            // 1.广场收藏+1
            plazaMapper.increaseFavorites(plazaEntity.getId(), 1);
            // 2.新增用户收藏记录
            Date date = new Date();
            userWorksMapper.insert(plazaEntity.getWorksId(), userProfile.getId(), UserWorksTypeEnum.FAVORITES.getCode(), UserWorksSourceEnum.PLAZA.getCode(), date, userProfile.getMobile(), date);
        } else {
            // 取消收藏
            // 1.广场收藏-1
            plazaMapper.decreaseFavorites(plazaEntity.getId(), 1);
            // 2. 删除用户收藏记录
            userWorksMapper.deleteById(userWorksEntity.getId());
        }
        return new PlazaLikeResponse();
    }

    /**
     * 广场作品分享
     *
     * @param userProfile 用户信息
     * @param id          id
     * @return 响应
     */
    public PlazaForwardResponse share(UserProfile userProfile, Long id) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (!plazaEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NOT_EXIST);
        }
        PlazaEntity plazaEntity = plazaEntityOptional.get();
        plazaMapper.increaseShare(plazaEntity.getId(), 1);
        return new PlazaForwardResponse();
    }

    /**
     * 获取详情
     *
     * @param userProfile 用户信息
     * @param id          id
     * @return 响应
     */
    public PlazaInfoResponse getDetail(UserProfile userProfile, Long id) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (!plazaEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NOT_EXIST);
        }
        PlazaEntity plazaEntity = plazaEntityOptional.get();
        PlazaInfoResponse plazaInfoResponse = PlazaMapStruct.INSTANCE.entityToInfoResponse(plazaEntity);
        UserInfoEntity userInfoEntity = userInfoMapper.findByUserId(Long.parseLong(plazaInfoResponse.getUserId()));
        if (Objects.nonNull(userInfoEntity)) {
            plazaInfoResponse.setAvatar(StringUtils.isBlank(userInfoEntity.getAvatar()) ? userProperties.getDefaultAvatar() : userInfoEntity.getAvatar());
            plazaInfoResponse.setUserName(StringUtils.isBlank(userInfoEntity.getName()) ? userProperties.getDefaultName() : userInfoEntity.getName());
        }
        if (Objects.nonNull(userProfile)) {
            UserWorksEntity userWorksEntity = userWorksMapper.queryByWorksAndSource(userProfile.getId(), plazaEntity.getWorksId(), UserWorksSourceEnum.PLAZA.getCode());
            if (Objects.nonNull(userWorksEntity)) {
                plazaInfoResponse.setFavorites(1);
            } else {
                plazaInfoResponse.setFavorites(0);
            }
        } else {
            plazaInfoResponse.setFavorites(0);
        }
        return plazaInfoResponse;
    }

    /**
     * 查询作品id详情
     *
     * @param userProfile 用户信息
     * @param workId      作品id
     * @return 响应
     */
    public Result<WorksInfoResponse> getWorksDetail(UserProfile userProfile, Long workId) {
        Optional<WorksEntity> worksEntityOptional = worksRepository.findById(workId);
        if (worksEntityOptional.isPresent()) {
            WorksEntity worksEntity = worksEntityOptional.get();
            WorksInfoResponse worksInfoResponse = WorksMapStruct.INSTANCE.entityToInfoResponse(worksEntity);
            return Result.success(worksInfoResponse);
        }
        return Result.error(ResultCodeEnum.PLAZA_NOT_EXIST);
    }

    /**
     * 广场发布
     *
     * @param userProfile 用户信息
     * @param request     请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public AdminPublishPlazaResponse publishPlaza(UserProfile userProfile, AdminPublishPlazaRequest request) {
        Long worksId = Long.parseLong(request.getWorksId());
        PlazaEntity plazaEntity = plazaMapper.queryByWorksId(worksId);
        if (Objects.nonNull(plazaEntity)) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_EXISTS);
        }
        Optional<WorksEntity> worksEntityOptional = worksRepository.findById(worksId);
        if (!worksEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.WORK_NOT_EXIST);
        }
        PlazaEntity entity = new PlazaEntity();
        entity.setWorksId(worksId);
        entity.setUserId(userProfile.getId());
        entity.setCoverPage(request.getCoverPage());
        entity.setBanner(JSON.toJSONString(request.getBanner()));
        entity.setTitle(request.getTitle());
        entity.setContent(request.getContent());
        entity.setLikeCount(0);
        entity.setDislikeCount(0);
        entity.setFavoritesCount(0);
        entity.setShareCount(0);
        entity.setCreatedAt(new Date());
        entity.setCreator(userProfile.getMobile());
        PlazaEntity saved = plazaRepository.save(entity);
        return PlazaMapStruct.INSTANCE.entityToPublishResponse(saved);
    }

    /**
     * 更新广场内容
     *
     * @param userProfile 用户信息
     * @param id          广场id
     * @param request     请求变更体
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public AdminUpdatePlazaResponse updatePlaza(UserProfile userProfile, Long id, AdminUpdatePlazaRequest request) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (!plazaEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NOT_EXIST);
        }
        PlazaEntity plazaEntity = plazaEntityOptional.get();
        if (!plazaEntity.getUserId().equals(userProfile.getId())) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NO_UPDATE_PERMISSION);
        }
        Long worksId = Long.parseLong(request.getWorksId());
        // 校验作品是否存在
        Optional<WorksEntity> worksEntityOptional = worksRepository.findById(worksId);
        if (!worksEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.WORK_NOT_EXIST);
        }
        if (!plazaEntity.getWorksId().equals(worksId)) {
            // 校验作品是否发布广场
            PlazaEntity workPlazaEntity = plazaMapper.queryByWorksId(worksId);
            if (Objects.nonNull(workPlazaEntity)) {
                throw new APIRuntimeException(ResultCodeEnum.PLAZA_EXISTS);
            }
        }
        plazaEntity.setTitle(request.getTitle());
        plazaEntity.setContent(request.getContent());
        plazaEntity.setWorksId(worksId);
        plazaEntity.setCoverPage(request.getCoverPage());
        plazaEntity.setBanner(JSON.toJSONString(request.getBanner()));
        PlazaEntity updated = plazaRepository.save(plazaEntity);
        return PlazaMapStruct.INSTANCE.entityToUpdateResponse(updated);
    }

    /**
     * 管理端分页查询广场列表
     *
     * @param pageNum  当前页
     * @param pageSize 页数量
     * @return 广场列表
     */
    public Result<PageResult<AdminPlazaPageListResponse>> pageList(int pageNum, int pageSize) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<PlazaListResponse> plazaEntityList = plazaMapper.queryPage(null, null);
        if (CollectionUtils.isEmpty(plazaEntityList)) {
            return Result.success(new PageResult<>());
        }
        List<AdminPlazaPageListResponse> plazaPageList = PlazaMapStruct.INSTANCE.listToPageListResponse(plazaEntityList);
        // 查询用户信息
        List<String> userIdList = plazaPageList.stream().map(AdminPlazaPageListResponse::getUserId).collect(Collectors.toList());
        List<UserInfoEntity> userInfoEntityList = userInfoMapper.queryByUserIdList(userIdList);
        Map<Long, UserInfoEntity> userInfoMap = Optional.ofNullable(userInfoEntityList).orElse(Collections.emptyList()).stream().collect(Collectors.toMap(UserInfoEntity::getUserId, t -> t, (t1, t2) -> t1));
        for (AdminPlazaPageListResponse plazaListResponse : plazaPageList) {
            UserInfoEntity userInfoEntity = userInfoMap.get(Long.parseLong(plazaListResponse.getUserId()));
            if (Objects.nonNull(userInfoEntity)) {
                plazaListResponse.setAvatar(StringUtils.isBlank(userInfoEntity.getAvatar()) ? userProperties.getDefaultAvatar() : userInfoEntity.getAvatar());
                plazaListResponse.setUserName(StringUtils.isBlank(userInfoEntity.getName()) ? userProperties.getDefaultName() : userInfoEntity.getName());
            }
        }
        PageInfo<AdminPlazaPageListResponse> plazaPageInfo = new PageInfo<>(plazaPageList);
        plazaPageInfo.setPageNum(pageNum);
        plazaPageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(plazaPageInfo, plazaPageList);
    }

    /**
     * 广场内容删除
     *
     * @param userProfile 用户信息
     * @param id          广场id
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public void plazaDelete(UserProfile userProfile, Long id) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (!plazaEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NOT_EXIST);
        }
        PlazaEntity plazaEntity = plazaEntityOptional.get();
        if (!plazaEntity.getUserId().equals(userProfile.getId())) {
            throw new APIRuntimeException(ResultCodeEnum.PLAZA_NO_UPDATE_PERMISSION);
        }
        plazaRepository.deleteById(id);
    }

    /**
     * 查询广场详情
     *
     * @param userProfile 用户id
     * @param id          广场id
     * @return 广场详情
     */
    public AdminPlazaInfoResponse plazaDetail(UserProfile userProfile, Long id) {
        Optional<PlazaEntity> plazaEntityOptional = plazaRepository.findById(id);
        if (plazaEntityOptional.isPresent()) {
            AdminPlazaInfoResponse response = PlazaMapStruct.INSTANCE.entityToDetail(plazaEntityOptional.get());
            UserInfoEntity userInfoEntity = userInfoMapper.findByUserId(Long.parseLong(response.getUserId()));
            if (Objects.nonNull(userInfoEntity)) {
                response.setAvatar(StringUtils.isBlank(userInfoEntity.getAvatar()) ? userProperties.getDefaultAvatar() : userInfoEntity.getAvatar());
                response.setUserName(StringUtils.isBlank(userInfoEntity.getName()) ? userProperties.getDefaultName() : userInfoEntity.getName());
            }
            return response;
        }
        return new AdminPlazaInfoResponse();
    }
}
